package com.zx.sdk.league.member;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.gson.Gson;
import com.mbridge.msdk.MBridgeSDK;
import com.mbridge.msdk.mbbid.out.BidListennning;
import com.mbridge.msdk.mbbid.out.BidLossCode;
import com.mbridge.msdk.mbbid.out.BidManager;
import com.mbridge.msdk.mbbid.out.BidResponsed;
import com.mbridge.msdk.mbbid.out.SplashBidRequestParams;
import com.mbridge.msdk.newinterstitial.out.MBBidInterstitialVideoHandler;
import com.mbridge.msdk.newinterstitial.out.MBNewInterstitialHandler;
import com.mbridge.msdk.newinterstitial.out.NewInterstitialListener;
import com.mbridge.msdk.out.MBBidRewardVideoHandler;
import com.mbridge.msdk.out.MBRewardVideoHandler;
import com.mbridge.msdk.out.MBSplashHandler;
import com.mbridge.msdk.out.MBSplashLoadListener;
import com.mbridge.msdk.out.MBSplashShowListener;
import com.mbridge.msdk.out.MBridgeIds;
import com.mbridge.msdk.out.MBridgeSDKFactory;
import com.mbridge.msdk.out.RewardInfo;
import com.mbridge.msdk.out.RewardVideoListener;
import com.zx.sdk.ZxSDK;
import com.zx.sdk.listener.BaseZxRewardListener;
import com.zx.sdk.listener.BaseZxSplashListener;
import com.zx.sdk.model.AdInfo;
import com.zx.sdk.model.ReadyAdPosition;
import com.zx.sdk.model.ZxError;
import com.zx.sdk.util.ConfigHelper;
import com.zx.sdk.util.LogHelper;
import com.zx.sdk.util.RunnableHelper;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class MTG extends BaseLeagueMember<Object, Object, Object, Object, Object> {

    /**
     * 用来存放bid广告的价格和token
     */
    private final HashMap<String, BidResponsed> bidResponsedMap = new HashMap<>();
    /**
     * 在bid广告胜出后直接加载并显示时，用来传递对象
     */
    private BaseZxRewardListener mBaseZxRewardListener = null;

    @Override
    public String getName() {
        return "mtg";
    }

    @Override
    protected void onInit(Context context, String appId, boolean initialized) {
        if (initialized) return;
        MBridgeSDK sdk = MBridgeSDKFactory.getMBridgeSDK();
        Map<String, String> map = sdk.getMBConfigurationMap(appId.split("@@")[0], appId.split("@@")[1], ZxSDK.getWxAppId());
        sdk.init(map, context);
    }

    @Override
    protected void onLoadSplash(AdInfo adInfo, ViewGroup container, String mode, String type, BaseZxSplashListener listener) {
        if (AdInfo.AD_TYPE_EXPRESS_INTERSTITIAL_AD == adInfo.getAdType()) {
            onLoadInterstitial((Activity) container.getContext(), adInfo, mode, type, new BaseZxRewardListener() {
                @Override
                public void onADClick() {
                    listener.onADClicked();
                }

                @Override
                public void onADClose() {
                    listener.onADDismissed();
                }

                @Override
                public void onADExpose() {
                    listener.onADExposure();
                }

                @Override
                public void onADLoad() {
                    listener.onADLoaded(0L);
                }

                @Override
                public void onReward(@NonNull Map<String, Object> map) {

                }

                @Override
                public void onVideoCached() {

                }

                @Override
                public void onVideoComplete() {

                }

                @Override
                public void onPreLoadADError(ZxError error) {
                    listener.onPreLoadNoAD(error);
                }

                @Override
                public void onRewardStepVerify(int taskType, int currentTaskStatus) {

                }

                @Override
                public void onAdSkip(float v) {

                }

                @Override
                public void onVideoPlayError(ZxError error) {
                }

                @Override
                public void onNoAD(ZxError error) {
                    listener.onNoAD(error);
                }

                @Override
                public void onPreloading() {
                    listener.onPreloading();
                }

                @Override
                public void onLoaded() {
                    listener.onLoaded();
                }
            });
            return;
        }
        String pid = adInfo.getMapPid();
        String placementId = pid.split("@@")[0];
        String unitID = pid.split("@@")[1];
        if (ZxSDK.Bidding.equals(type)) {
            BidManager manager = new BidManager(new SplashBidRequestParams(placementId, unitID));
            manager.setBidListener(new BidListennning() {
                @Override
                public void onFailed(String msg) {
                    LogHelper.d("MTG 请求价格失败", pid, msg);
                    onLoadSplashError(msg, mode, listener, adInfo);
                }

                @Override
                public void onSuccessed(BidResponsed bidResponsed) {
                    bidResponsedMap.put(pid, bidResponsed);
                    // 获取价格成功就模拟广告已加载，真正胜出需要显示的时候再去加载并显示
                    MBSplashHandler mbSplashHandler = getMBSplashHandler(pid, container, ZxSDK.FETCH_AND_SHOW, listener, adInfo, placementId, unitID);
                    splashMap.put(pid, mbSplashHandler);
                }
            });
            manager.bid();
        } else {
            innerLoadSplash(pid, container, mode, listener, adInfo, placementId, unitID);
        }
    }

    private void innerLoadSplash(String pid, ViewGroup container, String mode, BaseZxSplashListener listener, AdInfo adInfo, String placementId, String unitID) {
        MBSplashHandler mbSplashHandler = getMBSplashHandler(pid, container, mode, listener, adInfo, placementId, unitID);
        switch (mode) {
            case ZxSDK.FETCH_ONLY:
                mbSplashHandler.preLoad();
                break;
            case ZxSDK.FETCH_AND_SHOW:
                mbSplashHandler.loadAndShow(container);
                break;
        }
    }

    @NonNull
    private MBSplashHandler getMBSplashHandler(String pid, ViewGroup container, String mode, BaseZxSplashListener listener, AdInfo adInfo, String placementId, String unitID) {
        MBSplashHandler mbSplashHandler = new MBSplashHandler((Activity) container.getContext(), placementId, unitID);
        if (container.getContext() instanceof Activity) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                Application.ActivityLifecycleCallbacks[] callback = new Application.ActivityLifecycleCallbacks[1];
                callback[0] = new Application.ActivityLifecycleCallbacks() {
                    @Override
                    public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {

                    }

                    @Override
                    public void onActivityStarted(@NonNull Activity activity) {

                    }

                    @Override
                    public void onActivityResumed(@NonNull Activity activity) {
                        mbSplashHandler.onResume();
                    }

                    @Override
                    public void onActivityPaused(@NonNull Activity activity) {
                        mbSplashHandler.onPause();
                    }

                    @Override
                    public void onActivityStopped(@NonNull Activity activity) {

                    }

                    @Override
                    public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {

                    }

                    @Override
                    public void onActivityDestroyed(@NonNull Activity activity) {
                        mbSplashHandler.onDestroy();
                        ((Activity) container.getContext()).unregisterActivityLifecycleCallbacks(callback[0]);
                    }
                };
                ((Activity) container.getContext()).registerActivityLifecycleCallbacks(callback[0]);
            }
        }
        mbSplashHandler.setSplashLoadListener(new MBSplashLoadListener() {
            @Override
            public void onLoadSuccessed(MBridgeIds ids, int reqType) {
                listener.onADLoaded(MTG.this, 0, adInfo);
                if (ZxSDK.FETCH_ONLY.equals(mode)) {
                    saveSplash(pid, mbSplashHandler, container);
                }
            }

            @Override
            public void onLoadFailed(MBridgeIds ids, String msg, int reqType) {
                onLoadSplashError(msg, mode, listener, adInfo);
            }

            @Override
            public void isSupportZoomOut(MBridgeIds mBridgeIds, boolean b) {

            }
        });
        mbSplashHandler.setSplashShowListener(new MBSplashShowListener() {
            @Override
            public void onShowSuccessed(MBridgeIds ids) {
                listener.onADExposure(MTG.this, adInfo);
            }

            @Override
            public void onShowFailed(MBridgeIds ids, String msg) {
                switch (mode) {
                    case ZxSDK.FETCH_ONLY:
                        listener.onPreLoadNoAD(MTG.this, new ZxError("-1", msg), adInfo);
                        break;
                    case ZxSDK.FETCH_AND_SHOW:
                        listener.onNoAD(MTG.this, new ZxError("-1", msg), adInfo);
                        break;
                }
            }

            @Override
            public void onAdClicked(MBridgeIds ids) {
                listener.onADClicked(MTG.this, adInfo);
            }

            @Override
            public void onDismiss(MBridgeIds ids, int type) {
                listener.onADDismissed(MTG.this, adInfo);
            }

            @Override
            public void onAdTick(MBridgeIds ids, long millisUntilFinished) {
                listener.onADTick(MTG.this, millisUntilFinished, adInfo);
            }

            @Override
            public void onZoomOutPlayStart(MBridgeIds mBridgeIds) {

            }

            @Override
            public void onZoomOutPlayFinish(MBridgeIds mBridgeIds) {

            }
        });
        return mbSplashHandler;
    }

    private void onLoadSplashError(String msg, String mode, BaseZxSplashListener listener, AdInfo adInfo) {
        switch (mode) {
            case ZxSDK.FETCH_ONLY:
                listener.onPreLoadNoAD(MTG.this, new ZxError("-1", msg), adInfo);
                break;
            case ZxSDK.FETCH_AND_SHOW:
                listener.onNoAD(MTG.this, new ZxError("-1", msg), adInfo);
                break;
        }
    }

    @Override
    public boolean onShowSplash(AdInfo adInfo, ViewGroup container, @Nullable Object adv, BaseZxSplashListener listener) {
        if (AdInfo.AD_TYPE_EXPRESS_INTERSTITIAL_AD == adInfo.getAdType() && onShowInterstitial((Activity) container.getContext(), adInfo, adv, new BaseZxRewardListener() {
            @Override
            public void onADClick() {
                listener.onADClicked();
            }

            @Override
            public void onADClose() {
                listener.onADDismissed();
            }

            @Override
            public void onADExpose() {
                listener.onADExposure();
            }

            @Override
            public void onADLoad() {
                listener.onADLoaded(0L);
            }

            @Override
            public void onReward(@NonNull Map<String, Object> map) {

            }

            @Override
            public void onVideoCached() {

            }

            @Override
            public void onVideoComplete() {

            }

            @Override
            public void onPreLoadADError(ZxError error) {
                listener.onPreLoadNoAD(error);
            }

            @Override
            public void onRewardStepVerify(int taskType, int currentTaskStatus) {

            }

            @Override
            public void onAdSkip(float v) {

            }

            @Override
            public void onVideoPlayError(ZxError error) {
            }

            @Override
            public void onNoAD(ZxError error) {
                listener.onNoAD(error);
            }

            @Override
            public void onPreloading() {
                listener.onPreloading();
            }

            @Override
            public void onLoaded() {
                listener.onLoaded();
            }
        })) {
            return true;
        } else if (adv instanceof MBSplashHandler) {
            if (bidResponsedMap.containsKey(adInfo.getMapPid())) {
                ((MBSplashHandler) adv).loadAndShowByToken(bidResponsedMap.get(adInfo.getMapPid()).getBidToken(), container);
            } else {
                ((MBSplashHandler) adv).show(container);
            }
            return true;
        }
        return false;
    }

    @Override
    public void onLoadReward(Activity context, AdInfo adInfo, String mode, String
            type, BaseZxRewardListener listener) {
        // 如是bidding广告需要先获取价格
        if (AdInfo.AD_TYPE_EXPRESS_INTERSTITIAL_AD == adInfo.getAdType()) {
            onLoadInterstitial(context, adInfo, mode, type, listener);
            return;
        }
        String pid = adInfo.getMapPid();
        String placementId = pid.split("@@")[0];
        String unitID = pid.split("@@")[1];
        mBaseZxRewardListener = listener;
        if (ZxSDK.Bidding.equals(type)) {
            BidManager manager = new BidManager(placementId, unitID);
            manager.setBidListener(new BidListennning() {
                @Override
                public void onFailed(String errorMsg) {
                    LogHelper.d("MTG 请求价格失败", pid, errorMsg);
                    onLoadAdError(errorMsg, mode, listener, adInfo);
                }

                @Override
                public void onSuccessed(BidResponsed bidResponsed) {
                    bidResponsedMap.put(pid, bidResponsed);
                    // 获取价格成功就模拟广告已加载，真正胜出需要显示的时候再去加载并显示
                    rewardMap.put(pid, new Object());
                    mBaseZxRewardListener = listener;
                }
            });
            manager.bid();
        } else {
            MBRewardVideoHandler mMBRewardVideoHandler = new MBRewardVideoHandler(context, placementId, unitID);
            mMBRewardVideoHandler.setRewardVideoListener(getRewardListener(mMBRewardVideoHandler, adInfo, mode, listener));
            RunnableHelper.runOnUIThread(() -> {
                mMBRewardVideoHandler.load();
            });
        }
    }

    private RewardVideoListener getRewardListener(final Object mMBRewardVideoHandler, AdInfo
            adInfo, String mode, BaseZxRewardListener listener) {
        return new RewardVideoListener() {

            @Override
            public void onLoadSuccess(MBridgeIds ids) {
            }

            @Override
            public void onVideoLoadSuccess(MBridgeIds ids) {
                listener.onADLoad(MTG.this, adInfo);
                switch (mode) {
                    case ZxSDK.FETCH_ONLY:
                        saveReward(adInfo.getMapPid(), mMBRewardVideoHandler);
                        break;
                    case ZxSDK.FETCH_AND_SHOW:
                        if (mMBRewardVideoHandler instanceof MBRewardVideoHandler) {
                            ((MBRewardVideoHandler) mMBRewardVideoHandler).show(ZxSDK.getUid(), new Gson().toJson(adInfo));
                        } else if (mMBRewardVideoHandler instanceof MBBidRewardVideoHandler) {
                            ((MBBidRewardVideoHandler) mMBRewardVideoHandler).showFromBid(ZxSDK.getUid(), new Gson().toJson(adInfo));
                        }
                        break;
                }
            }

            @Override
            public void onVideoLoadFail(MBridgeIds ids, String errorMsg) {
                onLoadAdError(errorMsg, mode, listener, adInfo);
            }

            @Override
            public void onShowFail(MBridgeIds ids, String errorMsg) {
                listener.onVideoPlayError(MTG.this, new ZxError("-1", errorMsg), adInfo);
            }

            @Override
            public void onAdShow(MBridgeIds ids) {
                listener.onADExpose(MTG.this, adInfo);
            }

            @Override
            public void onAdClose(MBridgeIds ids, RewardInfo rewardInfo) {
                listener.onADClose(MTG.this, adInfo);
                if (rewardInfo.isCompleteView()) {
                    listener.onReward(MTG.this, Collections.emptyMap(), adInfo);
                }
            }

            @Override
            public void onVideoAdClicked(MBridgeIds ids) {
                listener.onADClick(MTG.this, adInfo);
            }

            @Override
            public void onVideoComplete(MBridgeIds ids) {
                listener.onVideoComplete(MTG.this, adInfo);
            }

            @Override
            public void onEndcardShow(MBridgeIds ids) {
            }
        };
    }

    private NewInterstitialListener getInterstitialListener(final Object adv, AdInfo
            adInfo, String mode, BaseZxRewardListener listener) {
        return new NewInterstitialListener() {

            @Override
            public void onShowFail(MBridgeIds ids, String errorMsg) {
                listener.onVideoPlayError(MTG.this, new ZxError("-1", errorMsg), adInfo);
            }

            @Override
            public void onAdClicked(MBridgeIds mBridgeIds) {
                listener.onADClick(MTG.this, adInfo);
            }

            @Override
            public void onLoadCampaignSuccess(MBridgeIds mBridgeIds) {

            }

            @Override
            public void onResourceLoadSuccess(MBridgeIds mBridgeIds) {
                listener.onADLoad(MTG.this, adInfo);
                switch (mode) {
                    case ZxSDK.FETCH_ONLY:
                        if (ZxSDK.REWARD.equals(adInfo.getDisplay())) {
                            saveReward(adInfo.getMapPid(), adv);
                        } else {
                            saveInterstitial(adInfo.getMapPid(), adv);
                        }
                        break;
                    case ZxSDK.FETCH_AND_SHOW:
                        if (adv instanceof MBNewInterstitialHandler) {
                            ((MBNewInterstitialHandler) adv).show();
                        } else if (adv instanceof MBBidInterstitialVideoHandler) {
                            ((MBBidInterstitialVideoHandler) adv).showFromBid();
                        }
                        break;
                }
            }

            @Override
            public void onResourceLoadFail(MBridgeIds mBridgeIds, String s) {
                onLoadAdError(s, mode, listener, adInfo);
            }

            @Override
            public void onAdShow(MBridgeIds ids) {
                listener.onADExpose(MTG.this, adInfo);
            }

            @Override
            public void onAdClose(MBridgeIds ids, RewardInfo rewardInfo) {
                if (rewardInfo.isCompleteView()) {
                    listener.onReward(MTG.this, Collections.emptyMap(), adInfo);
                }
                listener.onADClose(MTG.this, adInfo);
            }

            @Override
            public void onVideoComplete(MBridgeIds ids) {
                listener.onVideoComplete(MTG.this, adInfo);
            }

            @Override
            public void onAdCloseWithNIReward(MBridgeIds mBridgeIds, RewardInfo rewardInfo) {

            }

            @Override
            public void onEndcardShow(MBridgeIds ids) {
            }
        };
    }

    @Override
    public int getCpmByPid(String type, String pid) {
        int cpm = super.getCpmByPid(type, pid);
        if (bidResponsedMap.containsKey(pid)) {
            try {
                // 单位是美元，换算成人民币的分
                cpm = (int) (Double.parseDouble(bidResponsedMap.get(pid).getPrice()) * 100 * ConfigHelper.getExchangeRate());
                LogHelper.d("MTG 请求价格成功", pid, Double.parseDouble(bidResponsedMap.get(pid).getPrice()) * 100 * ConfigHelper.getExchangeRate() + "");
                LogHelper.d("MTG 请求价格成功", pid, bidResponsedMap.get(pid).getPrice() + "美元 ", cpm + "分人民币");
            } catch (Exception ignored) {
            }
        }
        cpmCache.put(type + pid, cpm);
        return cpm;
    }

    private void onLoadAdError(String errorMsg, String mode, BaseZxRewardListener
            listener, AdInfo adInfo) {
        switch (mode) {
            case ZxSDK.FETCH_ONLY:
                listener.onPreLoadADError(MTG.this, new ZxError("-1", errorMsg), adInfo);
                break;
            case ZxSDK.FETCH_AND_SHOW:
                listener.onNoAD(MTG.this, new ZxError("-1", errorMsg), adInfo);
                break;
        }
    }

    @Override
    public boolean onShowReward(Activity context, AdInfo adInfo, @Nullable Object
            reward, BaseZxRewardListener listener) {
        if (AdInfo.AD_TYPE_EXPRESS_INTERSTITIAL_AD == adInfo.getAdType() && onShowInterstitial(context, adInfo, reward, listener)) {
            return true;
        }
        if (reward instanceof MBRewardVideoHandler) {
            ((MBRewardVideoHandler) reward).show(ZxSDK.getUid(), new Gson().toJson(adInfo));
        } else if (reward != null) {
            String pid = adInfo.getMapPid();
            if (!bidResponsedMap.containsKey(pid)) {
                return false;
            }
            MBBidRewardVideoHandler mMBRewardVideoHandler = new MBBidRewardVideoHandler(context, pid.split("@@")[0], pid.split("@@")[1]);
            mMBRewardVideoHandler.setRewardVideoListener(getRewardListener(mMBRewardVideoHandler, adInfo, ZxSDK.FETCH_AND_SHOW, mBaseZxRewardListener));
            mMBRewardVideoHandler.loadFromBid(bidResponsedMap.get(pid).getBidToken());
        }
        return true;
    }

    @Override
    public void onLoadInterstitial(Activity context, AdInfo adInfo, String mode, String
            type, BaseZxRewardListener listener) {
        String pid = adInfo.getMapPid();
        String placementId = pid.split("@@")[0];
        String unitID = pid.split("@@")[1];
        mBaseZxRewardListener = listener;
        if (ZxSDK.Bidding.equals(type)) {
            BidManager manager = new BidManager(placementId, unitID);
            manager.setBidListener(new BidListennning() {
                @Override
                public void onFailed(String errorMsg) {
                    LogHelper.d("MTG 请求价格失败", pid, errorMsg);
                    onLoadAdError(errorMsg, mode, listener, adInfo);
                }

                @Override
                public void onSuccessed(BidResponsed bidResponsed) {
                    bidResponsedMap.put(pid, bidResponsed);
                    // 获取价格成功就模拟广告已加载，真正胜出需要显示的时候再去加载并显示
                    if (ZxSDK.SPLASH.equals(adInfo.getDisplay())) {
                        saveSplash(pid, new Object(), null);
                    } else if (ZxSDK.REWARD.equals(adInfo.getDisplay())) {
                        rewardMap.put(pid, new Object());
                    } else if (ZxSDK.INTERSTITIAL.equals(adInfo.getDisplay())) {
                        interstitialMap.put(pid, new Object());
                    }
                    mBaseZxRewardListener = listener;
                }
            });
            manager.bid();
        } else {
            MBNewInterstitialHandler ad = new MBNewInterstitialHandler(context, placementId, unitID);
            ad.setInterstitialVideoListener(getInterstitialListener(ad, adInfo, mode, listener));
            RunnableHelper.runOnUIThread(() -> {
                ad.load();
            });
        }
    }

    @Override
    public boolean onShowInterstitial(Activity context, AdInfo adInfo, @Nullable Object
            adv, BaseZxRewardListener listener) {
        if (adv instanceof MBNewInterstitialHandler) {
            ((MBNewInterstitialHandler) adv).show();
        } else if (adv != null) {
            String pid = adInfo.getMapPid();
            if (!bidResponsedMap.containsKey(pid)) {
                return false;
            }
            MBBidInterstitialVideoHandler tmpAdv = new MBBidInterstitialVideoHandler(context, pid.split("@@")[0], pid.split("@@")[1]);
            tmpAdv.setInterstitialVideoListener(getInterstitialListener(tmpAdv, adInfo, ZxSDK.FETCH_AND_SHOW, mBaseZxRewardListener));
            tmpAdv.loadFromBid(bidResponsedMap.get(pid).getBidToken());
        }
        return true;
    }

    @Override
    public boolean isPreResReady(String type, String pid) {
        Object adv = getFilledRewardByPid(pid);
        if (adv instanceof MBRewardVideoHandler) {
            return ((MBRewardVideoHandler) adv).isReady();
        }
        if (adv instanceof MBNewInterstitialHandler) {
            return ((MBNewInterstitialHandler) adv).isReady();
        }
        return super.isPreResReady(type, pid);
    }

    @Override
    public void clearFilledBiddingAd(String type, String pid) {
        super.clearFilledBiddingAd(type, pid);
        bidResponsedMap.remove(pid);
    }

    @Override
    public void notifyBiddingWin(String type, String mapPid, @Nullable ReadyAdPosition loser) {
        BidResponsed bidResponsed = bidResponsedMap.get(mapPid);
        if (bidResponsed == null) {
            return;
        }
        bidResponsed.sendWinNotice(ZxSDK.getContext().getApplicationContext());
        LogHelper.d(getName(), "notifyBiddingWin", mapPid, "selfPrice =" + getCpmByPid(type, mapPid), "LoserPrice = " + (loser != null ? loser.getCpm() : 0));
    }

    @Override
    public void notifyBiddingLose(String type, String mapPid, ReadyAdPosition
            winner, ZxSDK.LoseReason reason) {
        BidResponsed bidResponsed = bidResponsedMap.get(mapPid);
        if (bidResponsed == null) {
            return;
        }
        bidResponsed.sendLossNotice(ZxSDK.getContext().getApplicationContext(), BidLossCode.bidPriceNotHighest());
        LogHelper.d(getName(), "notifyBiddingLose", mapPid, "selfPrice =" + getCpmByPid(type, mapPid), "WinnerPrice = " + winner.getCpm());

    }
}